/*
 * chapter_9.cpp
 *
 *  Created on: 2020年11月19日
 *      Author: san
 */

#include <iostream>
#include <vector>
#include <string>
#include <deque>
#include <list>
#include <forward_list>
#include <fstream>
#include <sstream>
#include <stack>

#include "Sales_data.h"

using std::forward_list;
using std::ifstream;
using std::istringstream;

int t9_2()
{
	std::list<int> l;
	return 0;
}

bool searchInt(std::vector<int> v, int num)
{
	/*
	 * 接受一对指向vector<int>的迭代器和一个int值
	 */
	for (auto i: v)
	{
		if (i == num)
			return true;
	}
	return false;
}

int t9_4()
{

	std::vector<int> v{1,2,3,4,4,5,6,7,8,10};
	if (searchInt(v, 10))
	{
		std::cout << "find!!!" << std::endl;
	}
	return 0;
}

int printVeci(std::vector<int> ivec)
{
	for (auto i: ivec)
	{
		std::cout << " " << i;
	}
	std::cout << std::endl;
	return 0;
}

int t9_11()
{
	/*
	 * 容器的六种初始化方法
	 */
	std::vector<int> v0{1};
	std::vector<int> v1 = {0,1,2};
	std::vector<int> v2(10);
	std::vector<int> v3(10, 10);
	std::vector<int> v4(v1.crbegin(), v1.crend());
	std::vector<int> v5(v1);

	std::vector<std::vector<int>> ivvec = {v0, v1, v2, v3, v4, v5};
	int n = 0;
	for (auto ivec: ivvec)
	{
		std::cout << "v" << n++ << ": ";
		printVeci(ivec);
	}

	return 0;
}

int t9_13()
{
	/*
	 * 接受容器和迭代器的区别
	 */
	std::vector<int> v0{1,2,3,4,5};
//	std::vector<double> vd(v0);
	std::vector<double> vd(v0.crbegin(), v0.crend());
	std::vector<int> v1(v0);
}

int t9_14()
{
	std::vector<std::string> svec{"hello world!"};
	std::list<char*> slist{"hello china!"};
	// 这里报错
//	svec[0].assign(std::begin(slist[0]), std::end(slist[0]));
	return 0;
}

int t9_18()
{
	std::deque<string> sdeq{};
	for (int i = 0; i < 5; ++i)
	{
		string s;
		std::getline(std::cin, s);
		sdeq.push_back(s);
	}

	for (auto s: sdeq)
	{
		std::cout << s << std::endl;
	}
	return 0;
}

int t9_20()
{
	std::list<int> ilist{1,2,3,4,5,6,7,8,9};
	std::deque<int> ideq1;
	std::deque<int> ideq2;

	for (int i: ilist)
	{
		if (i % 2 == 0)
			ideq1.push_back(i);
		else if (i % 2 != 0)
			ideq2.push_back(i);
		else
			std::cerr << "ERROR! Expected int but get others" << std::endl;
	}
	return 0;
}

int t9_22_origin()
{
	/*
	 * 原始版本是死循环
	 */
	std::vector<int> ivec{1,2,3,4};
	ivec.reserve(5);
	int some_val = 4, i = 0;
	std::vector<int>::iterator iter = ivec.begin(),
			mid = ivec.begin() + ivec.size() / 2;

	while (iter != mid)
	{
		if (*iter == some_val)
			iter = ivec.insert(iter, some_val * 2);
		else
			++iter;
		std::cout << ++i << std::endl;
	}

	for (int i: ivec)
		std::cout << i << " ";
	std::cout << std::endl;
	return 0;
}

int t9_24()
{
	std::vector<int> ivec{1, 2, 3, 4, 5};
	std::cout << ivec.at(0) << " " << ivec.front() << " " << ivec.back() << " " << ivec[0];
}

int t9_26()
{
	std::list<int> ilist{1,2,3,4,5,6,7,8,9};
	std::vector<int> ivec{};
	std::list<int>::iterator iter_beg = ilist.begin(),
			iter_end = ilist.end();

	for (iter_beg; iter_beg != iter_end; ++iter_beg)
	{
		if (*iter_beg % 2 != 0)
		{
			ivec.push_back(*iter_beg);
			iter_beg = ilist.erase(iter_beg);
		}
	}

	for (int i: ivec)
		std::cout << i << " ";
	std::cout << std::endl;

	for (int i: ilist)
		std::cout << i << " ";
	std::cout << std::endl;
	return 0;
}

int t9_25()
{
	/*
	 * 若传入erase的是两个相等的迭代器,则不会执行删除操作,并且迭代器不会失效
	 */
	std::vector<int> ivec{1, 2, 3, 4, 5};
	std::vector<int>::iterator iter = ivec.begin(), iterend = ivec.end();
	ivec.erase(iterend, iterend);
	std::cout << "测试两个都是相同的情况下迭代器是否会失效: " << *iter << std::endl;

	for (int i: ivec)
	{
		std::cout << i << " ";
	}
	std::cout << std::endl;
	return 0;
}

void findAndInsert(forward_list<string> &ilf, const string &s1, const string &s2)
{
	forward_list<string>::iterator temp, beg = ilf.begin(),
			end = ilf.end();  // 保存尾迭代器并在后面的程序种使用是一个坏主意
	bool flag = false;
	while (beg != end)
	{
		if (*beg == s1)
		{
			ilf.insert_after(beg, s2);
			flag = true;
			break;
		}
		temp = beg++;
	}

	if (flag)
		return;
	ilf.insert_after(temp, s2);
}

int t9_28()
{
	/*
	 * 测试erase_after 和 before_begin
	 */
	forward_list<string> sfl{"hello world!", "hello C plus plus!"};
	findAndInsert(sfl, "hello world", "hello guys!");
	for (string s: sfl)
		std::cout << s << std::endl;
	return 0;
}

int t9_31()
{
	std::vector<int> vi{0,1,2,3,4,5,6,7,8,9};
	auto iter = vi.begin();
	while (iter != vi.end())
	{
		if (*iter % 2)
		{
			iter = vi.insert(iter, *iter);
			std::advance(iter, 2);
		}
		else
		{
			iter = vi.erase(iter);
		}
	}
	return 0;
}

int t9_31_2()
{
	forward_list<int> fi{0,1,2,3,4,5,6,7,8,9};
	auto iter = fi.begin();
	auto prev = fi.before_begin();
	while (iter != fi.end())
	{
		if (*iter %2 == 0)
		{
			iter = fi.insert_after(prev, *iter);
			std::advance(iter, 2);
			std::advance(prev, 2);
		}
		else
		{
			iter = fi.erase_after(prev);
		}
	}

	for (auto i: fi)
	{
		std::cout << i << " ";
	}
	std::cout << std::endl;
}

int t9_33()
{

	std::vector<int> ivec{1,2,3,4,5,6,7};
	std::vector<int>::iterator begin = ivec.begin();
	while (begin != ivec.end())
	{
		++begin;
		begin = ivec.insert(begin, 42);  // insert操作导致迭代器失效
		++begin;
	}

	for (auto i: ivec)
	{
		std::cout << i << " ";
	}

	std::cout << std::endl;
	return 0;
}

int t9_38()
{
	/*
	 * 探究vector是如何增长的
	 */
	std::vector<int> ivec{0};
	ivec.resize(5000);
	std::cout << "ivec: size: " << ivec.size()
			<< " capacity: " << ivec.capacity() << std::endl;
	ivec.push_back(0);
	std::cout << "ivec: size: " << ivec.size()
				<< " capacity: " << ivec.capacity() << std::endl;
	for (int i = 0; i < 10000; ++i)
	{
		ivec.push_back(i + 7);
	}
	std::cout << "ivec: size: " << ivec.size()
				<< " capacity: " << ivec.capacity() << std::endl;
	for (int i = 0; i < 20000; ++i)
	{
		ivec.push_back(i + 7);
	}
	std::cout << "ivec: size: " << ivec.size()
				<< " capacity: " << ivec.capacity() << std::endl;
	for (int i = 0; i < 40000; ++i)
	{
		ivec.push_back(i + 7);
	}
	std::cout << "ivec: size: " << ivec.size()
				<< " capacity: " << ivec.capacity() << std::endl;
	for (int i = 0; i < 80000; ++i)
	{
		ivec.push_back(i + 7);
	}
	std::cout << "ivec: size: " << ivec.size()
				<< " capacity: " << ivec.capacity() << std::endl;
	for (int i = 0; i < 160000; ++i)
	{
		ivec.push_back(i + 7);
	}
	std::cout << "ivec: size: " << ivec.size()
				<< " capacity: " << ivec.capacity() << std::endl;
	for (int i = 0; i < 320000; ++i)
	{
		ivec.push_back(i + 7);
	}
	std::cout << "ivec: size: " << ivec.size()
				<< " capacity: " << ivec.capacity() << std::endl;
	for (int i = 0; i < 640000; ++i)
	{
		ivec.push_back(i + 7);
	}
	std::cout << "ivec: size: " << ivec.size()
				<< " capacity: " << ivec.capacity() << std::endl;
	for (int i = 0; i < 1280000; ++i)
	{
		ivec.push_back(i + 7);
	}
	std::cout << "ivec: size: " << ivec.size()
				<< " capacity: " << ivec.capacity() << std::endl;
	for (int i = 0; i < 12800; ++i)
	{
		ivec.push_back(i + 7);
	}
	std::cout << "ivec: size: " << ivec.size()
				<< " capacity: " << ivec.capacity() << std::endl;

	return 0;
}

int t9_40()
{
	std::vector<int> ivec{1,2,3,4};
	ivec.reserve(5);

	for (int i = 5; i < 25; ++i)
	{
		ivec.push_back(i);
	}
	std::cout << "ivec: size: " << ivec.size()
					<< " capacity: " << ivec.capacity() << std::endl;
	ivec.resize(15);
	std::cout << "ivec: size: " << ivec.size()
					<< " capacity: " << ivec.capacity() << std::endl;
}

int t9_41()
{
	/*
	 * 使用char*对string进行初始化
	 */
	char* s0 = "hello!, world";
	string s1(s0);
	std::cout << s1 << std::endl;
	string s2(s0, 5);
	std::cout << s2 << std::endl;
	return 0;
}

void shortToALL(string &s, const string &oldValue, const string &newVal)
{
	string::iterator ster = s.begin();
	string::const_iterator oter = oldValue.cbegin();

	for (ster; ster != (s.end() - oldValue.size() + 1); ++ster)
	{
		if (s.substr(ster - s.begin(), oldValue.size()) == oldValue)
		{
			ster = s.erase(ster, ster + oldValue.size());
			ster = s.insert(ster, newVal.begin(), newVal.end());
		}
	}
}

int t9_43()
{

	string s0 = "Tho I am z, I am nb";
	shortToALL(s0, "Tho", "Through");
	std::cout << "s0: " << s0;
	return 0;
}

void shortToAll2(string &s, const string &oldVal, const string &newVal)
{
	string::iterator ster = s.begin();

	for (ster; ster != (s.end() - oldVal.size() + 1); ++ster)
	{
		if (s.substr(ster - s.begin(), oldVal.size()) == oldVal)
		{
			s.replace(ster, ster + oldVal.size(), newVal);
			ster = s.begin();
		}
	}
}

int t9_44()
{

	string s0 = "Tho I am z, I am nb";
	shortToAll2(s0, "Tho", "Through");
	std::cout << "s0: " << s0 << std::endl;
	return 0;
}

int t9_47()
{

	string s0 = "ab2c3d7R4E6";
	string numbers = "0123456789";
	string alphbet = "abcdefghijklmnopqrstABCDEFGHIJKLMNOPQRST";
	string::size_type pos = 0;
	std::cout << "numbers of s0: " << std::endl;
	while ((pos = s0.find_first_of(numbers, pos)) != string::npos)
	{
		std::cout << s0.at(pos) << " ";
		++pos;
	}
	return 0;
}

string findLongestMidWord(ifstream &inf)
{
	string word, result;
	unsigned lenght = 0;
	string middle_words = "aceimnorsuvwxz";
	while (inf >> word)
	{
		if (word.find_first_not_of(middle_words) == string::npos)
		{
			if (word.size() > lenght)
			{
				std::cout << "1" << std::endl;
				lenght = word.size();
				result = word;
			}
		}

	}

	return result;
}

int t9_49()
{
	ifstream inf("/home/san/eclipse-workspace/CppPrimer/Sources/a.txt");
	string result = findLongestMidWord(inf);
	if (result == "")
		std::cout << "不存在这样的单词" << std::endl;
	else
		std::cout << "Get it: " << result << " its size: " << result.size() << std::endl;;
	return 0;
}

class Str2Date{
public:
	Str2Date(){
		//
	}

private:
	unsigned year;
	unsigned month;
	unsigned day;
};

int t9_51()
{

	return 0;
}

int prio(char x)
{
    if(x=='*'||x=='/')  return 2;
    if(x=='+'||x=='-')  return 1;
    if(x=='(')  return 0;
    else return -1;

}

std::string midToPost(const std::string &s)
{

	/*
	 * 中缀表达式转换为后缀表达式
	 * 1. 如果数字直接输出
	 * 2. 如果是左括号，入栈
	 * 3. 如果是右括号，一直弹栈到遇到左括号
	 * 4. 如果是运算符，比较优先级，弹出优先级大的
	 */

	std::string result;
	std::stack<char> cs;
	for (char c: s)
	{
		if (c >= '0' && c <= '9')
		{
			result.push_back(c);
			result.push_back(' ');
		}
		else
		{
			if (cs.empty())
			{
				cs.push(c);
			}
			else if ('(' == c)
				cs.push(c);
			else if (')' == c)
			{
				while (cs.top() != '(')
				{
					result.push_back(cs.top());
					result.push_back(' ');
					cs.pop();
				}
			}
			else
			{
				while (prio(c) <= prio(cs.top()))
				{
					result.push_back(cs.top());
					result.push_back(' ');
					cs.pop();

					if (cs.empty())
						break;
				}

				cs.push(c);
			}
		}
	}

	while (!cs.empty())
	{
		if (cs.top() == '(')
			cs.pop();
		else
		{
			result.push_back(cs.top());
			result.push_back(' ');
			cs.pop();
		}
	}

	return result;

}

int t9_52()
{
	string s = "(1+2)/3";
	string post = midToPost(s);
	std::cout << "中缀表达式： " << s << std::endl
			<< "后缀表达式： " << post;
	return 0;
}

int main09()
{
//	t9_2();
//	t9_4();

	std::cout << "------------------六种初始化方法-----------------" << std::endl;
	t9_11();
	t9_13();
	std::cout << "------------------assign初始化方法-----------------" << std::endl;
	std::list<std::string> slist1(1);
	slist1.assign(10, "Hyha");

	for (auto s: slist1)
	{
		std::cout << s << " ";
	}
	std::cout << std::endl;

	std::cout << "------------------swap超快的（常数时间）-----------------" << std::endl;
	/*
	 * swap交换时，并未对元素本身进行交换，而是交换了两个容器的内部结构
	 */

	std::list<std::string> slist2(12, "haha");
	slist2.swap(slist1);
	for (auto s: slist1)
	{
		std::cout << s << " ";
	}
	std::cout << std::endl;

	std::cout << "----------------emplace操作：将参数传递给构造函数-------------------" << std::endl;
	std::vector<Sales_data> sdvec{};
	sdvec.emplace_back("Y0001");  // 可以看到构造函数被调用： （我是被委托人）
	for (auto sd: sdvec)
	{
		std::cout << sd.toString() << std::endl;
	}

	std::cout << "----------------练习9.3.1-------------------" << std::endl;
//	t9_18();
//	t9_20();
	t9_22_origin(); // 改动也写在origin里面了

	std::cout << "-----------------测试insert之后的迭代器失效------------------" << std::endl;
	// 可以看到insert之后迭代器失效了,并指向了未知地址
	std::vector<int> ivec2{1, 2, 3, 4, 5, 6, 7, 8};
	std::vector<int>::iterator iter2 = ivec2.begin();
	std::cout << "insert之前: " << *iter2 << std::endl;
	ivec2.insert(iter2 + 2, 1);
	std::cout << "insert之后: " << *iter2 << std::endl;
//	t9_33();  // 无效的指针

	std::cout << "-----------------访问和删除操作------------------" << std::endl;
	t9_24();
	std::cout << std::endl;
	t9_25();
	t9_26();
	t9_28();
	t9_31_2();

	std::cout << "-----------------vector是如何增长的------------------" << std::endl;
	t9_38();  // 翻倍
	t9_40();

	std::cout << "-----------------string的额外操作------------------" << std::endl;
	t9_41();
	t9_43();
	std::cout << std::endl;
	t9_44();

	std::cout << "-----------------string的搜索操作------------------" << std::endl;
	t9_47();
	t9_49();

	std::cout << "-----------------string的数值转换------------------" << std::endl;
	string s1 = "1 + 2";
	int result = stoi(s1);
	std::cout << "result: " << result << std::endl;

	std::cout << "-----------------stack栈的使用------------------" << std::endl;
	t9_52();


	return 0;
}


